﻿using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;

namespace FTG.Testing.Utils
{
#if NET20
    public delegate void Action();
#endif
    public class XTATestRunner
    {
        Exception _ThreadException;
        Action _action;

        /// <summary>
        /// Runs action in STA
        /// </summary>
        /// <param name="action"></param>
        public void RunSTA(Action action) {
            Run(action, ApartmentState.STA);
        }

        /// <summary>
        /// Runs action in MTA
        /// </summary>
        /// <param name="action"></param>
        public void RunMTA(Action action) {
            Run(action, ApartmentState.MTA);
        }

        /// <summary>
        /// Runs the specified action.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <param name="apartmentState">thread apartment state</param>
        /// <exception cref="System.ArgumentNullException">action is null</exception>
        /// <exception cref="System.ArgumentException">invalid apartment state</exception>
        public void Run(Action action, ApartmentState apartmentState){
            if (action == null) {
                throw new ArgumentNullException();
            }
            if (apartmentState == ApartmentState.Unknown) {
                throw new ArgumentException();
            }

            _action = action;
            Thread t = new Thread(_Run);
            t.SetApartmentState(apartmentState);
            t.Start();
            t.Join();
            if (_ThreadException != null) {
                throw _ThreadException;
            }
        }

        void _Run() {
            try {
                _action();
            }
            catch (Exception ex) {
                var ctx = new StreamingContext(StreamingContextStates.CrossAppDomain);
                var mgr = new ObjectManager(null, ctx);
                var si = new SerializationInfo(ex.GetType(), new FormatterConverter());

                ex.GetObjectData(si, ctx);
                mgr.RegisterObject(ex, 1, si);
                mgr.DoFixups(); 
                _ThreadException = ex;
            }
        }
    
    }
}
